Пример #1
0
HRESULT NINE_WINAPI
NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
                                     D3DDEVTYPE DeviceType,
                                     D3DFORMAT AdapterFormat,
                                     D3DFORMAT RenderTargetFormat,
                                     D3DFORMAT DepthStencilFormat )
{
    struct pipe_screen *screen;
    enum pipe_format dfmt, bfmt, zsfmt;
    HRESULT hr;

    DBG("This=%p DeviceType=%s AdapterFormat=%s "
        "RenderTargetFormat=%s DepthStencilFormat=%s\n", This,
        nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),
        d3dformat_to_string(RenderTargetFormat),
        d3dformat_to_string(DepthStencilFormat));

    user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);
    user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);

    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    if (FAILED(hr)) { return hr; }

    dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
                                       PIPE_BIND_DISPLAY_TARGET |
                                       PIPE_BIND_SHARED, FALSE, FALSE);
    bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat,
                                       PIPE_TEXTURE_2D, 0,
                                       PIPE_BIND_RENDER_TARGET, FALSE, FALSE);
    if (RenderTargetFormat == D3DFMT_NULL)
        bfmt = dfmt;
    zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat,
                                        PIPE_TEXTURE_2D, 0,
                                        d3d9_get_pipe_depth_format_bindings(DepthStencilFormat),
                                        FALSE, FALSE);
    if (dfmt == PIPE_FORMAT_NONE ||
        bfmt == PIPE_FORMAT_NONE ||
        zsfmt == PIPE_FORMAT_NONE) {
        return D3DERR_NOTAVAILABLE;
    }

    return D3D_OK;
}
Пример #2
0
HRESULT WINAPI
NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
                                         D3DDEVTYPE DeviceType,
                                         D3DFORMAT SurfaceFormat,
                                         BOOL Windowed,
                                         D3DMULTISAMPLE_TYPE MultiSampleType,
                                         DWORD *pQualityLevels )
{
    struct pipe_screen *screen;
    HRESULT hr;
    enum pipe_format pf;
    unsigned bind;

    DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
        "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
        d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
        pQualityLevels);

    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    if (FAILED(hr))
        return hr;

    if (depth_stencil_format(SurfaceFormat))
        bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);
    else /* render-target */
        bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ |
               PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_RENDER_TARGET;

    pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
                                     MultiSampleType, bind, FALSE);

    if (pf == PIPE_FORMAT_NONE) {
        DBG("%s with %u samples not available.\n",
            d3dformat_to_string(SurfaceFormat), MultiSampleType);
        return D3DERR_NOTAVAILABLE;
    }

    if (pQualityLevels)
        *pQualityLevels = 1; /* gallium doesn't have quality levels */

    return D3D_OK;
}
Пример #3
0
HRESULT NINE_WINAPI
NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
                                         D3DDEVTYPE DeviceType,
                                         D3DFORMAT SurfaceFormat,
                                         BOOL Windowed,
                                         D3DMULTISAMPLE_TYPE MultiSampleType,
                                         DWORD *pQualityLevels )
{
    struct pipe_screen *screen;
    HRESULT hr;
    enum pipe_format pf;
    unsigned bind;

    DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
        "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
        d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
        pQualityLevels);

    if (pQualityLevels) {
        /* In error cases return only 1 quality level supported */
        *pQualityLevels = 1;
    }
    user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL);

    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    if (FAILED(hr))
        return hr;

    if (depth_stencil_format(SurfaceFormat))
        bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);
    else /* render-target */
        bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;

    pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
                                     0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE);

    if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
        DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat));
        return D3DERR_INVALIDCALL;
    }

    pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
                                     MultiSampleType, bind, FALSE, FALSE);

    if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
        DBG("%s with %u samples not available.\n",
            d3dformat_to_string(SurfaceFormat), MultiSampleType);
        return D3DERR_NOTAVAILABLE;
    }

    if (pQualityLevels) {
        /* NONMASKABLE MultiSampleType might have more than one quality level,
         * while MASKABLE MultiSampleTypes have only one level.
         * Advertise quality levels and map each level to a sample count. */
         (void ) d3dmultisample_type_check(screen, SurfaceFormat,
                 &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels);
         DBG("advertising %u quality levels\n", *pQualityLevels);
    }

    return D3D_OK;
}
Пример #4
0
HRESULT NINE_WINAPI
NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
                                D3DDEVTYPE DeviceType,
                                D3DFORMAT AdapterFormat,
                                DWORD Usage,
                                D3DRESOURCETYPE RType,
                                D3DFORMAT CheckFormat )
{
    struct pipe_screen *screen;
    HRESULT hr;
    enum pipe_format pf;
    enum pipe_texture_target target;
    unsigned bind = 0;
    boolean srgb;

    /* Check adapter format. */

    DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,
        nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));
    DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType,
        d3dformat_to_string(CheckFormat));

    user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL);

    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    if (FAILED(hr))
        return hr;
    pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
                                     PIPE_BIND_DISPLAY_TARGET |
                                     PIPE_BIND_SHARED, FALSE, FALSE);
    if (pf == PIPE_FORMAT_NONE) {
        DBG("AdapterFormat %s not available.\n",
            d3dformat_to_string(AdapterFormat));
        return D3DERR_NOTAVAILABLE;
    }

    /* Check actual format. */

    switch (RType) {
    case D3DRTYPE_SURFACE:       target = PIPE_TEXTURE_2D; break;
    case D3DRTYPE_TEXTURE:       target = PIPE_TEXTURE_2D; break;
    case D3DRTYPE_CUBETEXTURE:   target = PIPE_TEXTURE_CUBE; break;
    case D3DRTYPE_VOLUME:        target = PIPE_TEXTURE_3D; break;
    case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;
    case D3DRTYPE_VERTEXBUFFER:  target = PIPE_BUFFER; break;
    case D3DRTYPE_INDEXBUFFER:   target = PIPE_BUFFER; break;
    default:
        user_assert(0, D3DERR_INVALIDCALL);
    }

    bind = 0;
    if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET;
    if (Usage & D3DUSAGE_DEPTHSTENCIL) {
        if (!depth_stencil_format(CheckFormat))
            return D3DERR_NOTAVAILABLE;
        bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat);
    }

    /* API hack because setting RT[0] to NULL is forbidden */
    if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&
        (RType == D3DRTYPE_SURFACE ||
         RType == D3DRTYPE_TEXTURE))
        return D3D_OK;

    /* RESZ hack */
    if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&
        RType == D3DRTYPE_SURFACE)
        return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?
               D3D_OK : D3DERR_NOTAVAILABLE;

    /* ATOC hack */
    if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE)
        return D3D_OK;

    if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) &&
        (Usage & D3DUSAGE_RENDERTARGET))
        bind |= PIPE_BIND_BLENDABLE;

    if (Usage & D3DUSAGE_DMAP) {
        DBG("D3DUSAGE_DMAP not available\n");
        return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */
    }

    switch (RType) {
    case D3DRTYPE_TEXTURE:       bind |= PIPE_BIND_SAMPLER_VIEW; break;
    case D3DRTYPE_CUBETEXTURE:   bind |= PIPE_BIND_SAMPLER_VIEW; break;
    case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
    case D3DRTYPE_VERTEXBUFFER:  bind |= PIPE_BIND_VERTEX_BUFFER; break;
    case D3DRTYPE_INDEXBUFFER:   bind |= PIPE_BIND_INDEX_BUFFER; break;
    case D3DRTYPE_SURFACE:
        if (!(Usage & D3DUSAGE_DEPTHSTENCIL))
            bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
        /* Offscreen surface support: Usage = 0.
         * In practice drivers are very restrictive on the formats supported.
         * Basically a few common formats + YUV and compressed formats. The
         * reason is that offscreen surface are useful only for directdraw
         * compatibility (a WONTIMPL of nine) + format conversion (useful in
         * particular for YUV because the format was not advertised for textures
         * on NV chips). */
        if (Usage == 0)
            bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */
    default:
        break;
    }


    srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;
    pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target,
                                     0, bind, srgb, FALSE);
    if (pf == PIPE_FORMAT_NONE) {
        DBG("NOT AVAILABLE\n");
        return D3DERR_NOTAVAILABLE;
    }

    /* we support ATI1 and ATI2 hack only for 2D and Cube textures */
    if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE &&
        (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2))
        return D3DERR_NOTAVAILABLE;
    /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */
    /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */

    if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))
        return D3DOK_NOAUTOGEN;
    return D3D_OK;
}
Пример #5
0
HRESULT
NineSwapChain9_Resize( struct NineSwapChain9 *This,
                       D3DPRESENT_PARAMETERS *pParams,
                       D3DDISPLAYMODEEX *mode )
{
    struct NineDevice9 *pDevice = This->base.device;
    D3DSURFACE_DESC desc;
    HRESULT hr;
    struct pipe_resource *resource, tmplt;
    enum pipe_format pf;
    BOOL has_present_buffers = FALSE;
    int depth;
    unsigned i, oldBufferCount, newBufferCount;
    D3DMULTISAMPLE_TYPE multisample_type;

    DBG("This=%p pParams=%p\n", This, pParams);
    user_assert(pParams != NULL, E_POINTER);
    user_assert(pParams->SwapEffect, D3DERR_INVALIDCALL);
    user_assert((pParams->SwapEffect != D3DSWAPEFFECT_COPY) ||
                (pParams->BackBufferCount <= 1), D3DERR_INVALIDCALL);
    user_assert(pDevice->ex || pParams->BackBufferCount <=
                D3DPRESENT_BACK_BUFFERS_MAX, D3DERR_INVALIDCALL);
    user_assert(!pDevice->ex || pParams->BackBufferCount <=
                D3DPRESENT_BACK_BUFFERS_MAX_EX, D3DERR_INVALIDCALL);
    user_assert(pDevice->ex ||
                (pParams->SwapEffect == D3DSWAPEFFECT_FLIP) ||
                (pParams->SwapEffect == D3DSWAPEFFECT_COPY) ||
                (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD), D3DERR_INVALIDCALL);

    DBG("pParams(%p):\n"
        "BackBufferWidth: %u\n"
        "BackBufferHeight: %u\n"
        "BackBufferFormat: %s\n"
        "BackBufferCount: %u\n"
        "MultiSampleType: %u\n"
        "MultiSampleQuality: %u\n"
        "SwapEffect: %u\n"
        "hDeviceWindow: %p\n"
        "Windowed: %i\n"
        "EnableAutoDepthStencil: %i\n"
        "AutoDepthStencilFormat: %s\n"
        "Flags: %s\n"
        "FullScreen_RefreshRateInHz: %u\n"
        "PresentationInterval: %x\n", pParams,
        pParams->BackBufferWidth, pParams->BackBufferHeight,
        d3dformat_to_string(pParams->BackBufferFormat),
        pParams->BackBufferCount,
        pParams->MultiSampleType, pParams->MultiSampleQuality,
        pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed,
        pParams->EnableAutoDepthStencil,
        d3dformat_to_string(pParams->AutoDepthStencilFormat),
        nine_D3DPRESENTFLAG_to_str(pParams->Flags),
        pParams->FullScreen_RefreshRateInHz,
        pParams->PresentationInterval);

    if (pParams->BackBufferCount == 0) {
        pParams->BackBufferCount = 1;
    }

    if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) {
        pParams->BackBufferFormat = D3DFMT_A8R8G8B8;
    }

    This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0;
    /* +1 because we add the fence of the current buffer before popping an old one */
    if (This->desired_fences > DRI_SWAP_FENCES_MAX)
        This->desired_fences = DRI_SWAP_FENCES_MAX;

    if (This->actx->vblank_mode == 0)
        pParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    else if (This->actx->vblank_mode == 3)
        pParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    if (mode && This->mode) {
        *(This->mode) = *mode;
    } else if (mode) {
        This->mode = malloc(sizeof(D3DDISPLAYMODEEX));
        memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX));
    } else {
        free(This->mode);
        This->mode = NULL;
    }

    /* Note: It is the role of the backend to fill if necessary
     * BackBufferWidth and BackBufferHeight */
    hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode);
    if (hr != D3D_OK)
        return hr;

    oldBufferCount = This->num_back_buffers;
    newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams);

    multisample_type = pParams->MultiSampleType;

    /* Map MultiSampleQuality to MultiSampleType */
    hr = d3dmultisample_type_check(This->screen, pParams->BackBufferFormat,
                                   &multisample_type,
                                   pParams->MultiSampleQuality,
                                   NULL);
    if (FAILED(hr)) {
        return hr;
    }

    pf = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat,
                                     PIPE_TEXTURE_2D, multisample_type,
                                     PIPE_BIND_RENDER_TARGET, FALSE, FALSE);

    if (This->actx->linear_framebuffer ||
        (pf != PIPE_FORMAT_B8G8R8X8_UNORM &&
        pf != PIPE_FORMAT_B8G8R8A8_UNORM) ||
        pParams->SwapEffect != D3DSWAPEFFECT_DISCARD ||
        multisample_type >= 2 ||
        (This->actx->ref && This->actx->ref == This->screen))
        has_present_buffers = TRUE;

    /* Note: the buffer depth has to match the window depth.
     * In practice, ARGB buffers can be used with windows
     * of depth 24. Windows of depth 32 are extremely rare.
     * So even if the buffer is ARGB, say it is depth 24.
     * It is common practice, for example that's how
     * glamor implements depth 24.
     * TODO: handle windows with other depths. Not possible in the short term.
     * For example 16 bits.*/
    depth = 24;

    memset(&tmplt, 0, sizeof(tmplt));
    tmplt.target = PIPE_TEXTURE_2D;
    tmplt.width0 = pParams->BackBufferWidth;
    tmplt.height0 = pParams->BackBufferHeight;
    tmplt.depth0 = 1;
    tmplt.last_level = 0;
    tmplt.array_size = 1;
    tmplt.usage = PIPE_USAGE_DEFAULT;
    tmplt.flags = 0;

    desc.Type = D3DRTYPE_SURFACE;
    desc.Pool = D3DPOOL_DEFAULT;
    desc.MultiSampleType = pParams->MultiSampleType;
    desc.MultiSampleQuality = pParams->MultiSampleQuality;
    desc.Width = pParams->BackBufferWidth;
    desc.Height = pParams->BackBufferHeight;

    for (i = 0; i < oldBufferCount; i++) {
        if (This->tasks[i])
            _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[i]));
    }
    memset(This->tasks, 0, sizeof(This->tasks));

    if (This->pool) {
        _mesa_threadpool_destroy(This, This->pool);
        This->pool = NULL;
    }
    This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY);
    if (This->enable_threadpool)
        This->pool = _mesa_threadpool_create(This);
    if (!This->pool)
        This->enable_threadpool = FALSE;

    for (i = 0; i < oldBufferCount; i++) {
        ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]);
        This->present_handles[i] = NULL;
        if (This->present_buffers[i])
            pipe_resource_reference(&(This->present_buffers[i]), NULL);
    }

    if (newBufferCount != oldBufferCount) {
        for (i = newBufferCount; i < oldBufferCount;
             ++i)
            NineUnknown_Detach(NineUnknown(This->buffers[i]));

        for (i = oldBufferCount; i < newBufferCount; ++i) {
            This->buffers[i] = NULL;
            This->present_handles[i] = NULL;
        }
    }
    This->num_back_buffers = newBufferCount;

    for (i = 0; i < newBufferCount; ++i) {
        tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
        tmplt.nr_samples = multisample_type;
        if (!has_present_buffers)
            tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS;
        tmplt.format = d3d9_to_pipe_format_checked(This->screen,
                                                   pParams->BackBufferFormat,
                                                   PIPE_TEXTURE_2D,
                                                   tmplt.nr_samples,
                                                   tmplt.bind, FALSE, FALSE);
        if (tmplt.format == PIPE_FORMAT_NONE)
            return D3DERR_INVALIDCALL;
        resource = This->screen->resource_create(This->screen, &tmplt);
        if (!resource) {
            DBG("Failed to create pipe_resource.\n");
            return D3DERR_OUTOFVIDEOMEMORY;
        }
        if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER)
            resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
        if (This->buffers[i]) {
            NineSurface9_SetMultiSampleType(This->buffers[i], desc.MultiSampleType);
            NineSurface9_SetResourceResize(This->buffers[i], resource);
            if (has_present_buffers)
                pipe_resource_reference(&resource, NULL);
        } else {
            desc.Format = pParams->BackBufferFormat;
            desc.Usage = D3DUSAGE_RENDERTARGET;
            hr = NineSurface9_new(pDevice, NineUnknown(This), resource, NULL, 0,
                                  0, 0, &desc, &This->buffers[i]);
            if (has_present_buffers)
                pipe_resource_reference(&resource, NULL);
            if (FAILED(hr)) {
                DBG("Failed to create RT surface.\n");
                return hr;
            }
            This->buffers[i]->base.base.forward = FALSE;
        }
        if (has_present_buffers) {
            tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM;
            tmplt.bind = NINE_BIND_PRESENTBUFFER_FLAGS;
            tmplt.nr_samples = 0;
            if (This->actx->linear_framebuffer)
                tmplt.bind |= PIPE_BIND_LINEAR;
            if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD)
                tmplt.bind |= PIPE_BIND_RENDER_TARGET;
            resource = This->screen->resource_create(This->screen, &tmplt);
            pipe_resource_reference(&(This->present_buffers[i]), resource);
        }
        This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth, false);
        pipe_resource_reference(&resource, NULL);
        if (!This->present_handles[i]) {
            return D3DERR_DRIVERINTERNALERROR;
        }
    }
    if (pParams->EnableAutoDepthStencil) {
        tmplt.bind = d3d9_get_pipe_depth_format_bindings(pParams->AutoDepthStencilFormat);
        tmplt.nr_samples = multisample_type;
        tmplt.format = d3d9_to_pipe_format_checked(This->screen,
                                                   pParams->AutoDepthStencilFormat,
                                                   PIPE_TEXTURE_2D,
                                                   tmplt.nr_samples,
                                                   tmplt.bind,
                                                   FALSE, FALSE);

        if (tmplt.format == PIPE_FORMAT_NONE)
            return D3DERR_INVALIDCALL;

        if (This->zsbuf) {
            resource = This->screen->resource_create(This->screen, &tmplt);
            if (!resource) {
                DBG("Failed to create pipe_resource for depth buffer.\n");
                return D3DERR_OUTOFVIDEOMEMORY;
            }

            NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType);
            NineSurface9_SetResourceResize(This->zsbuf, resource);
            pipe_resource_reference(&resource, NULL);
        } else {
            hr = NineDevice9_CreateDepthStencilSurface(pDevice,
                                                       pParams->BackBufferWidth,
                                                       pParams->BackBufferHeight,
                                                       pParams->AutoDepthStencilFormat,
                                                       pParams->MultiSampleType,
                                                       pParams->MultiSampleQuality,
                                                       0,
                                                       (IDirect3DSurface9 **)&This->zsbuf,
                                                       NULL);
            if (FAILED(hr)) {
                DBG("Failed to create ZS surface.\n");
                return hr;
            }
            NineUnknown_ConvertRefToBind(NineUnknown(This->zsbuf));
        }
    }

    This->params = *pParams;

    return D3D_OK;
}
Пример #6
0
HRESULT
NineSurface9_ctor( struct NineSurface9 *This,
                   struct NineUnknownParams *pParams,
                   struct NineUnknown *pContainer,
                   struct pipe_resource *pResource,
                   void *user_buffer,
                   uint8_t TextureType,
                   unsigned Level,
                   unsigned Layer,
                   D3DSURFACE_DESC *pDesc )
{
    HRESULT hr;
    union pipe_color_union rgba = {0};
    struct pipe_surface *surf;
    struct pipe_context *pipe = pParams->device->pipe;
    bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL;
    D3DMULTISAMPLE_TYPE multisample_type;

    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(allocate || pResource || user_buffer ||
           pDesc->Format == D3DFMT_NULL);
    assert(!allocate || (!pResource && !user_buffer));
    assert(!pResource || !user_buffer);
    assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT);
    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;

    multisample_type = pDesc->MultiSampleType;

    /* Map MultiSampleQuality to MultiSampleType */
    hr = d3dmultisample_type_check(pParams->device->screen,
                                   pDesc->Format,
                                   &multisample_type,
                                   pDesc->MultiSampleQuality,
                                   NULL);
    if (FAILED(hr)) {
        return hr;
    }

    /* 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;
    This->base.info.height0 = pDesc->Height;
    This->base.info.depth0 = 1;
    This->base.info.last_level = 0;
    This->base.info.array_size = 1;
    This->base.info.nr_samples = multisample_type;
    This->base.info.usage = PIPE_USAGE_DEFAULT;
    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,
                                                         This->base.info.target,
                                                         This->base.info.nr_samples,
                                                         This->base.info.bind,
                                                         FALSE,
                                                         pDesc->Pool == D3DPOOL_SCRATCH);

    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,
                                                         pDesc->Format,
                                                         This->base.info.target,
                                                         This->base.info.nr_samples,
                                                         This->base.info.bind,
                                                         FALSE,
                                                         TRUE);
    if (This->base.info.format != This->format_conversion) {
        This->data_conversion = align_calloc(
            nine_format_get_level_alloc_size(This->format_conversion,
                                             pDesc->Width,
                                             pDesc->Height,
                                             0), 32);
        if (!This->data_conversion)
            return E_OUTOFMEMORY;
        This->stride_conversion = nine_format_get_stride(This->format_conversion,
                                                         pDesc->Width);
    }

    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_calloc(
            nine_format_get_level_alloc_size(This->base.info.format,
                                             pDesc->Width,
                                             pDesc->Height,
                                             0), 32);
        if (!This->data)
            return E_OUTOFMEMORY;
    }

    hr = NineResource9_ctor(&This->base, pParams, pResource,
                            allocate && (pDesc->Pool == D3DPOOL_DEFAULT),
                            D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage);

    if (FAILED(hr))
        return hr;

    This->pipe = This->base.base.device->pipe;
    This->transfer = NULL;

    This->texture = TextureType;
    This->level = Level;
    This->level_actual = Level;
    This->layer = Layer;
    This->desc = *pDesc;

    This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width);

    if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC))
        This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;

    /* TODO: investigate what else exactly needs to be cleared */
    if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) {
        surf = NineSurface9_GetSurface(This, 0);
        pipe->clear_render_target(pipe, surf, &rgba, 0, 0, pDesc->Width, pDesc->Height, false);
    }

    NineSurface9_Dump(This);

    return D3D_OK;
}