Example #1
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;
}
Example #2
0
HRESULT
NineSwapChain9_Resize( struct NineSwapChain9 *This,
                       D3DPRESENT_PARAMETERS *pParams )
{
    struct NineDevice9 *pDevice = This->base.device;
    struct NineSurface9 **bufs;
    D3DSURFACE_DESC desc;
    HRESULT hr;
    struct pipe_resource *resource, tmplt;
    unsigned i;

    DBG("This=%p pParams=%p\n", This, pParams);
    if (pParams) {
        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->BackBufferFormat == D3DFMT_UNKNOWN)
        pParams->BackBufferFormat = This->params.BackBufferFormat;
    if (pParams->EnableAutoDepthStencil &&
        This->params.EnableAutoDepthStencil &&
        pParams->AutoDepthStencilFormat == D3DFMT_UNKNOWN)
        pParams->AutoDepthStencilFormat = This->params.AutoDepthStencilFormat;
    /* NULL means focus window.
    if (!pParams->hDeviceWindow && This->params.hDeviceWindow)
        pParams->hDeviceWindow = This->params.hDeviceWindow;
    */
    if (pParams->BackBufferCount == 0)
        pParams->BackBufferCount = 1; /* ref MSDN */

    if (pParams->BackBufferWidth == 0 || pParams->BackBufferHeight == 0) {
        RECT rect;
        if (!pParams->Windowed)
            return D3DERR_INVALIDCALL;
        if (FAILED(ID3DPresent_GetWindowRect(This->present, NULL, &rect))) {
            rect.right = This->params.BackBufferWidth;
            rect.bottom = This->params.BackBufferHeight;
        }
        if (!pParams->BackBufferWidth)
            pParams->BackBufferWidth = rect.right;
        if (!pParams->BackBufferHeight)
            pParams->BackBufferHeight = rect.bottom;
    }

    tmplt.target = PIPE_TEXTURE_2D;
    tmplt.width0 = pParams->BackBufferWidth;
    tmplt.height0 = pParams->BackBufferHeight;
    tmplt.depth0 = 1;
    tmplt.nr_samples = pParams->MultiSampleType;
    tmplt.last_level = 0;
    tmplt.array_size = 1;
    tmplt.usage = PIPE_USAGE_DEFAULT;
    tmplt.bind =
        PIPE_BIND_SAMPLER_VIEW |
        PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
    tmplt.flags = 0;

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

    if (pParams->BackBufferCount != This->params.BackBufferCount) {
        for (i = pParams->BackBufferCount; i < This->params.BackBufferCount;
             ++i)
            NineUnknown_Detach(NineUnknown(This->buffers[i]));

        bufs = REALLOC(This->buffers,
                       This->params.BackBufferCount * sizeof(This->buffers[0]),
                       pParams->BackBufferCount * sizeof(This->buffers[0]));
        if (!bufs)
            return E_OUTOFMEMORY;
        This->buffers = bufs;
        for (i = This->params.BackBufferCount; i < pParams->BackBufferCount;
             ++i)
            This->buffers[i] = NULL;
    }

    for (i = 0; i < pParams->BackBufferCount; ++i) {
        tmplt.format = d3d9_to_pipe_format(pParams->BackBufferFormat);
        tmplt.bind |= PIPE_BIND_RENDER_TARGET;
        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_SetResourceResize(This->buffers[i], resource);
            pipe_resource_reference(&resource, NULL);
        } else {
            desc.Format = pParams->BackBufferFormat;
            desc.Usage = D3DUSAGE_RENDERTARGET;
            hr = NineSurface9_new(pDevice, NineUnknown(This), resource, 0,
                                  0, 0, &desc, &This->buffers[i]);
            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 (pParams->EnableAutoDepthStencil) {
        tmplt.format = d3d9_to_pipe_format(pParams->AutoDepthStencilFormat);
        tmplt.bind &= ~PIPE_BIND_RENDER_TARGET;
        tmplt.bind |= PIPE_BIND_DEPTH_STENCIL;

        resource = This->screen->resource_create(This->screen, &tmplt);
        if (!resource) {
            DBG("Failed to create pipe_resource for depth buffer.\n");
            return D3DERR_OUTOFVIDEOMEMORY;
        }
        if (This->zsbuf) {
            NineSurface9_SetResourceResize(This->zsbuf, resource);
            pipe_resource_reference(&resource, NULL);
        } else {
            /* XXX wine thinks the container of this should the the device */
            desc.Format = pParams->AutoDepthStencilFormat;
            desc.Usage = D3DUSAGE_DEPTHSTENCIL;
            hr = NineSurface9_new(pDevice, NineUnknown(pDevice), resource, 0,
                                  0, 0, &desc, &This->zsbuf);
            pipe_resource_reference(&resource, NULL);
            if (FAILED(hr)) {
                DBG("Failed to create ZS surface.\n");
                return hr;
            }
            This->zsbuf->base.base.forward = FALSE;
        }
    }

    This->params = *pParams;

    return D3D_OK;
}