Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  8.  * license, and/or sell copies of the Software, and to permit persons to whom
  9.  * the Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
  22.  
  23. #include "c99_alloca.h"
  24.  
  25. #include "device9.h"
  26. #include "cubetexture9.h"
  27. #include "nine_helpers.h"
  28. #include "nine_pipe.h"
  29.  
  30. #define DBG_CHANNEL DBG_CUBETEXTURE
  31.  
  32.  
  33. static HRESULT
  34. NineCubeTexture9_ctor( struct NineCubeTexture9 *This,
  35.                        struct NineUnknownParams *pParams,
  36.                        UINT EdgeLength, UINT Levels,
  37.                        DWORD Usage,
  38.                        D3DFORMAT Format,
  39.                        D3DPOOL Pool,
  40.                        HANDLE *pSharedHandle )
  41. {
  42.     struct pipe_resource *info = &This->base.base.info;
  43.     struct pipe_screen *screen = pParams->device->screen;
  44.     enum pipe_format pf;
  45.     unsigned i, l, f, offset, face_size = 0;
  46.     unsigned *level_offsets;
  47.     D3DSURFACE_DESC sfdesc;
  48.     void *p;
  49.     HRESULT hr;
  50.  
  51.     DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d "
  52.         "Format=%d Pool=%d pSharedHandle=%p\n",
  53.         This, pParams, EdgeLength, Levels, Usage,
  54.         Format, Pool, pSharedHandle);
  55.  
  56.     user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) ||
  57.                 (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL);
  58.  
  59.     user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */
  60.  
  61.     if (Usage & D3DUSAGE_AUTOGENMIPMAP)
  62.         Levels = 0;
  63.  
  64.     pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0,
  65.                                      PIPE_BIND_SAMPLER_VIEW, FALSE);
  66.     if (pf == PIPE_FORMAT_NONE)
  67.         return D3DERR_INVALIDCALL;
  68.  
  69.     /* We support ATI1 and ATI2 hacks only for 2D textures */
  70.     if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2)
  71.         return D3DERR_INVALIDCALL;
  72.  
  73.     info->screen = pParams->device->screen;
  74.     info->target = PIPE_TEXTURE_CUBE;
  75.     info->format = pf;
  76.     info->width0 = EdgeLength;
  77.     info->height0 = EdgeLength;
  78.     info->depth0 = 1;
  79.     if (Levels)
  80.         info->last_level = Levels - 1;
  81.     else
  82.         info->last_level = util_logbase2(EdgeLength);
  83.     info->array_size = 6;
  84.     info->nr_samples = 0;
  85.     info->bind = PIPE_BIND_SAMPLER_VIEW;
  86.     info->usage = PIPE_USAGE_DEFAULT;
  87.     info->flags = 0;
  88.  
  89.     if (Usage & D3DUSAGE_RENDERTARGET)
  90.         info->bind |= PIPE_BIND_RENDER_TARGET;
  91.     if (Usage & D3DUSAGE_DEPTHSTENCIL)
  92.         info->bind |= PIPE_BIND_DEPTH_STENCIL;
  93.  
  94.     if (Usage & D3DUSAGE_DYNAMIC) {
  95.         info->usage = PIPE_USAGE_DYNAMIC;
  96.         info->bind |=
  97.             PIPE_BIND_TRANSFER_READ |
  98.             PIPE_BIND_TRANSFER_WRITE;
  99.     }
  100.     if (Usage & D3DUSAGE_SOFTWAREPROCESSING)
  101.         DBG("Application asked for Software Vertex Processing, "
  102.             "but this is unimplemented\n");
  103.  
  104.     if (Pool != D3DPOOL_DEFAULT) {
  105.         level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1));
  106.         face_size = nine_format_get_size_and_offsets(pf, level_offsets,
  107.                                                      EdgeLength, EdgeLength,
  108.                                                      info->last_level);
  109.         This->managed_buffer = MALLOC(6 * face_size);
  110.         if (!This->managed_buffer)
  111.             return E_OUTOFMEMORY;
  112.     }
  113.  
  114.     This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces));
  115.     if (!This->surfaces)
  116.         return E_OUTOFMEMORY;
  117.  
  118.     hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE,
  119.                                Format, Pool, Usage);
  120.     if (FAILED(hr))
  121.         return hr;
  122.     This->base.pstype = 2;
  123.  
  124.     /* Create all the surfaces right away.
  125.      * They manage backing storage, and transfers (LockRect) are deferred
  126.      * to them.
  127.      */
  128.     sfdesc.Format = Format;
  129.     sfdesc.Type = D3DRTYPE_SURFACE;
  130.     sfdesc.Usage = Usage;
  131.     sfdesc.Pool = Pool;
  132.     sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE;
  133.     sfdesc.MultiSampleQuality = 0;
  134.     /* We allocate the memory for the surfaces as continous blocks.
  135.      * This is the expected behaviour, however we haven't tested for
  136.      * cube textures in which order the faces/levels should be in memory
  137.      */
  138.     for (f = 0; f < 6; f++) {
  139.         offset = f * face_size;
  140.         for (l = 0; l <= info->last_level; l++) {
  141.             sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l);
  142.             p = This->managed_buffer ? This->managed_buffer + offset +
  143.                     level_offsets[l] : NULL;
  144.  
  145.             hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This),
  146.                                   This->base.base.resource, p, D3DRTYPE_CUBETEXTURE,
  147.                                   l, f, &sfdesc, &This->surfaces[f + 6 * l]);
  148.             if (FAILED(hr))
  149.                 return hr;
  150.         }
  151.     }
  152.  
  153.     for (i = 0; i < 6; ++i) /* width = 0 means empty, depth stays 1 */
  154.         This->dirty_rect[i].depth = 1;
  155.  
  156.     return D3D_OK;
  157. }
  158.  
  159. static void
  160. NineCubeTexture9_dtor( struct NineCubeTexture9 *This )
  161. {
  162.     unsigned i;
  163.  
  164.     DBG("This=%p\n", This);
  165.  
  166.     if (This->surfaces) {
  167.         for (i = 0; i < This->base.base.info.last_level * 6; ++i)
  168.             NineUnknown_Destroy(&This->surfaces[i]->base.base);
  169.         FREE(This->surfaces);
  170.     }
  171.  
  172.     if (This->managed_buffer)
  173.         FREE(This->managed_buffer);
  174.  
  175.     NineBaseTexture9_dtor(&This->base);
  176. }
  177.  
  178. HRESULT WINAPI
  179. NineCubeTexture9_GetLevelDesc( struct NineCubeTexture9 *This,
  180.                                UINT Level,
  181.                                D3DSURFACE_DESC *pDesc )
  182. {
  183.     DBG("This=%p Level=%u pDesc=%p\n", This, Level, pDesc);
  184.  
  185.     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
  186.     user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
  187.                 D3DERR_INVALIDCALL);
  188.  
  189.     *pDesc = This->surfaces[Level * 6]->desc;
  190.  
  191.     return D3D_OK;
  192. }
  193.  
  194. HRESULT WINAPI
  195. NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This,
  196.                                     D3DCUBEMAP_FACES FaceType,
  197.                                     UINT Level,
  198.                                     IDirect3DSurface9 **ppCubeMapSurface )
  199. {
  200.     const unsigned s = Level * 6 + FaceType;
  201.  
  202.     DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n",
  203.         This, FaceType, Level, ppCubeMapSurface);
  204.  
  205.     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
  206.     user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
  207.                 D3DERR_INVALIDCALL);
  208.     user_assert(FaceType < 6, D3DERR_INVALIDCALL);
  209.  
  210.     NineUnknown_AddRef(NineUnknown(This->surfaces[s]));
  211.     *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s];
  212.  
  213.     return D3D_OK;
  214. }
  215.  
  216. HRESULT WINAPI
  217. NineCubeTexture9_LockRect( struct NineCubeTexture9 *This,
  218.                            D3DCUBEMAP_FACES FaceType,
  219.                            UINT Level,
  220.                            D3DLOCKED_RECT *pLockedRect,
  221.                            const RECT *pRect,
  222.                            DWORD Flags )
  223. {
  224.     const unsigned s = Level * 6 + FaceType;
  225.  
  226.     DBG("This=%p FaceType=%d Level=%u pLockedRect=%p pRect=%p Flags=%d\n",
  227.         This, FaceType, Level, pLockedRect, pRect, Flags);
  228.  
  229.     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
  230.     user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP),
  231.                 D3DERR_INVALIDCALL);
  232.     user_assert(FaceType < 6, D3DERR_INVALIDCALL);
  233.  
  234.     return NineSurface9_LockRect(This->surfaces[s], pLockedRect, pRect, Flags);
  235. }
  236.  
  237. HRESULT WINAPI
  238. NineCubeTexture9_UnlockRect( struct NineCubeTexture9 *This,
  239.                              D3DCUBEMAP_FACES FaceType,
  240.                              UINT Level )
  241. {
  242.     const unsigned s = Level * 6 + FaceType;
  243.  
  244.     DBG("This=%p FaceType=%d Level=%u\n", This, FaceType, Level);
  245.  
  246.     user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL);
  247.     user_assert(FaceType < 6, D3DERR_INVALIDCALL);
  248.  
  249.     return NineSurface9_UnlockRect(This->surfaces[s]);
  250. }
  251.  
  252. HRESULT WINAPI
  253. NineCubeTexture9_AddDirtyRect( struct NineCubeTexture9 *This,
  254.                                D3DCUBEMAP_FACES FaceType,
  255.                                const RECT *pDirtyRect )
  256. {
  257.     DBG("This=%p FaceType=%d pDirtyRect=%p\n", This, FaceType, pDirtyRect);
  258.  
  259.     user_assert(FaceType < 6, D3DERR_INVALIDCALL);
  260.  
  261.     if (This->base.base.pool != D3DPOOL_MANAGED) {
  262.         if (This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP)
  263.             This->base.dirty_mip = TRUE;
  264.         return D3D_OK;
  265.     }
  266.     This->base.managed.dirty = TRUE;
  267.  
  268.     BASETEX_REGISTER_UPDATE(&This->base);
  269.  
  270.     if (!pDirtyRect) {
  271.         u_box_origin_2d(This->base.base.info.width0,
  272.                         This->base.base.info.height0,
  273.                         &This->dirty_rect[FaceType]);
  274.     } else {
  275.         struct pipe_box box;
  276.         rect_to_pipe_box_clamp(&box, pDirtyRect);
  277.         u_box_union_2d(&This->dirty_rect[FaceType], &This->dirty_rect[FaceType],
  278.                        &box);
  279.         (void) u_box_clip_2d(&This->dirty_rect[FaceType],
  280.                              &This->dirty_rect[FaceType],
  281.                              This->base.base.info.width0,
  282.                              This->base.base.info.height0);
  283.     }
  284.     return D3D_OK;
  285. }
  286.  
  287. IDirect3DCubeTexture9Vtbl NineCubeTexture9_vtable = {
  288.     (void *)NineUnknown_QueryInterface,
  289.     (void *)NineUnknown_AddRef,
  290.     (void *)NineUnknown_Release,
  291.     (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */
  292.     (void *)NineResource9_SetPrivateData,
  293.     (void *)NineResource9_GetPrivateData,
  294.     (void *)NineResource9_FreePrivateData,
  295.     (void *)NineResource9_SetPriority,
  296.     (void *)NineResource9_GetPriority,
  297.     (void *)NineBaseTexture9_PreLoad,
  298.     (void *)NineResource9_GetType,
  299.     (void *)NineBaseTexture9_SetLOD,
  300.     (void *)NineBaseTexture9_GetLOD,
  301.     (void *)NineBaseTexture9_GetLevelCount,
  302.     (void *)NineBaseTexture9_SetAutoGenFilterType,
  303.     (void *)NineBaseTexture9_GetAutoGenFilterType,
  304.     (void *)NineBaseTexture9_GenerateMipSubLevels,
  305.     (void *)NineCubeTexture9_GetLevelDesc,
  306.     (void *)NineCubeTexture9_GetCubeMapSurface,
  307.     (void *)NineCubeTexture9_LockRect,
  308.     (void *)NineCubeTexture9_UnlockRect,
  309.     (void *)NineCubeTexture9_AddDirtyRect
  310. };
  311.  
  312. static const GUID *NineCubeTexture9_IIDs[] = {
  313.     &IID_IDirect3DCubeTexture9,
  314.     &IID_IDirect3DBaseTexture9,
  315.     &IID_IDirect3DResource9,
  316.     &IID_IUnknown,
  317.     NULL
  318. };
  319.  
  320. HRESULT
  321. NineCubeTexture9_new( struct NineDevice9 *pDevice,
  322.                       UINT EdgeLength, UINT Levels,
  323.                       DWORD Usage,
  324.                       D3DFORMAT Format,
  325.                       D3DPOOL Pool,
  326.                       struct NineCubeTexture9 **ppOut,
  327.                       HANDLE *pSharedHandle )
  328. {
  329.     NINE_DEVICE_CHILD_NEW(CubeTexture9, ppOut, pDevice,
  330.                           EdgeLength, Levels,
  331.                           Usage, Format, Pool, pSharedHandle);
  332. }
  333.